package com.njust.service;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

import com.njust.dao.BookDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;


@Service
public class BookService {

    @Autowired
    BookDao bookDao;


//	@Autowired
//	BookService bookService;

    /**
     * 事务细节：
     * isolation-Isolation：事务的隔离级别;
     * propagation-Propagation：事务的传播行为
     * <p>
     * <p>
     * noRollbackFor-Class[]：哪些异常事务可以不回滚
     * noRollbackForClassName-String[]（String全类名）:
     * <p>
     * rollbackFor-Class[]:哪些异常事务需要回滚；
     * rollbackForClassName-String[]:
     * <p>
     * 异常分类：
     * 运行时异常（非检查异常）：可以不用处理；默认都回滚；
     * 编译时异常（检查异常）：要么try-catch，要么在方法上声明throws
     * 默认不回滚；
     * <p>
     * 事务的回滚：默认发生运行时异常都 回滚，发生编译时异常不会回滚；
     * noRollbackFor:哪些异常事务可以不回滚;（可以让原来默认回滚的异常给他不回滚）
     * noRollbackFor={ArithmeticException.class,NullPointerException.class}
     * noRollbackForClassName
     * <p>
     * rollbackFor：原本不回滚（原本编译时异常是不回滚的）的异常指定让其回滚；
     * <p>
     * readOnly-boolean：设置事务为只读事务：
     * 可以进行事务优化；
     * readOnly=true：加快查询速度；不用管事务那一堆操作了。
     * <p>
     * timeout-int（秒为单位）：超时：事务超出指定执行时长后自动终止并回滚
     *
     * @throws FileNotFoundException propagation-Propagation：事务的传播行为;
     *                               传播行为（事务的传播+事务的行为）；
     *                               如果有多个事务进行嵌套运行，子事务是否要和大事务共用一个事务；
     *                               传播行为:
     *                               AService{
     *                                  tx_a(){
     *                                      //a的一些方法
     *                                      tx_b(){
     *                                      }
     *                                      tx_c(){
     *                                      }
     *                                  }
     *                               }
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void checkout(String username, String isbn) {
        //1、减库存
        bookDao.updateStock(isbn);

        int price = bookDao.getPrice(isbn);

        //2、减余额
        bookDao.updateBalance(username, price);


    }


    @Transactional
    public void checkout1(String username, String isbn){
        //1、减库存
        bookDao.updateStock(isbn);

        int price = bookDao.getPrice(isbn);

        //2、减余额
        bookDao.updateBalance(username, price);

        int i = 10 / 0;

    }

    @Transactional(timeout = 3)
    public void checkout2(String username, String isbn) {
        //1、减库存
        bookDao.updateStock(isbn);

        int price = bookDao.getPrice(isbn);

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //2、减余额
        bookDao.updateBalance(username, price);
    }

    /**
     * readOnly-boolean：设置事务为只读事务：
     *      可以进行事务优化；
     *      readOnly=true：加快查询速度；不用管事务那一堆操作了。
     * @param username
     * @param isbn
     */
    @Transactional(readOnly = true)
    public void checkout3(String username, String isbn){
        //1、减库存
        bookDao.updateStock(isbn);

        int price = bookDao.getPrice(isbn);

        //2、减余额
        bookDao.updateBalance(username, price);
    }

    /**
     * 异常分类：
     *      运行时异常（非检查异常）：可以不用处理；默认都回滚；
     *      编译时异常（检查异常）：要么try-catch，要么在方法上声明throws，默认不回滚；
     * @param username
     * @param isbn
     * @throws FileNotFoundException
     */
    @Transactional
    public void checkout4(String username, String isbn) throws FileNotFoundException {
        //1、减库存
        bookDao.updateStock(isbn);

        int price = bookDao.getPrice(isbn);

        //2、减余额
        bookDao.updateBalance(username, price);

        new FileInputStream("D://hahahahha.aa");
    }

    /**
     * 事务的回滚：默认发生运行时异常都 回滚，发生编译时异常不会回滚；
     *      noRollbackFor:哪些异常事务可以不回滚;（可以让原来默认回滚的异常给他不回滚）
     *      noRollbackFor={ArithmeticException.class,NullPointerException.class}
     *      noRollbackForClassName
     * @param username
     * @param isbn
     */
    @Transactional(noRollbackFor = {ArithmeticException.class})
    public void checkout5(String username, String isbn){
        //1、减库存
        bookDao.updateStock(isbn);

        int price = bookDao.getPrice(isbn);

        //2、减余额
        bookDao.updateBalance(username, price);

        int i = 10 / 0;
    }

    /**
     * rollbackFor：原本不回滚（原本编译时异常是不回滚的）的异常指定让其回滚；
     * @param username
     * @param isbn
     * @throws FileNotFoundException
     */
    @Transactional(rollbackFor = {FileNotFoundException.class})
    public void checkout6(String username, String isbn) throws FileNotFoundException {
        //1、减库存
        bookDao.updateStock(isbn);

        int price = bookDao.getPrice(isbn);

        //2、减余额
        bookDao.updateBalance(username, price);

        new FileInputStream("D://hahahahha.aa");
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public void checkout7(String username, String isbn){
        //1、减库存
        bookDao.updateStock(isbn);

        int price = bookDao.getPrice(isbn);

        //2、减余额
        bookDao.updateBalance(username, price);

    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void checkout8(String username, String isbn){
        //1、减库存
        bookDao.updateStock(isbn);

        int price = bookDao.getPrice(isbn);

        //2、减余额
        bookDao.updateBalance(username, price);

    }

    @Transactional
    public void updatePrice(String isbn, int price) {
        bookDao.updatePrice(isbn, price);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public void updatePrice1(String isbn, int price) {
        bookDao.updatePrice(isbn, price);
        int i = 10 / 0;
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updatePrice2(String isbn, int price) {
        bookDao.updatePrice(isbn, price);
        int i = 10 / 0;
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updatePrice3(String isbn, int price) {
        bookDao.updatePrice(isbn, price);
    }



    /**
     * 根据业务的特性；进行调整
     * isolation=Isolation.READ_UNCOMMITTED:读出脏数据
     * <p>
     * <p>
     * READ_COMMITTED；实际上业务逻辑中用的最多的也是这个；
     * REPEATABLEP_READ；
     *
     * @param isbn
     * @return
     */
    @Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
    public int getPrice(String isbn) {
        return bookDao.getPrice(isbn);
    }


    @Transactional
    public void mulTx() {

        //ioc.getBean("BookSerice");
        checkout8("Tom", "ISBN-001");

        updatePrice3("ISBN-002", 998);

        int i = 10 / 0;
    }


}
